Passed
Push — development ( 26403f...98b3d9 )
by Vad
08:03 queued 49s
created

AuthService.validateUserById   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
1 7
import { Injectable } from '@nestjs/common';
2 7
import { JwtService } from '@nestjs/jwt';
3 7
import { HttpService } from '@nestjs/axios';
4 7
import { InjectRepository } from '@nestjs/typeorm';
5 7
import { Repository } from 'typeorm';
6 7
import { firstValueFrom } from 'rxjs';
7 7
import { ConfigService } from '@nestjs/config';
8 7
import { User } from '../users/entities/user.entity';
9
import { GithubUser } from './types/github-user.interface';
10
import { JwtPayload } from './types/jwt-payload.interface';
11
12
@Injectable()
13 7
export class AuthService {
14
  constructor(
15
    @InjectRepository(User)
16 9
    private userRepository: Repository<User>,
17 9
    private jwtService: JwtService,
18 9
    private httpService: HttpService,
19 9
    private configService: ConfigService,
20
  ) {}
21
22
  async exchangeGithubCode(code: string) {
23
    // console.log('Attempting exchange with code:', code);
24
    // console.log('Using client ID:', this.configService.get('OAUTH_CLIENT_ID'));
25
26 2
    const githubToken = await this.getGithubToken(code);
27 2
    const githubUser = await this.getGithubUser(githubToken);
28 2
    const user = await this.findOrCreateUser(githubUser);
29 2
    const token = this.createToken(user);
30
31 2
    return {
32
      access_token: token,
33
      user: {
34
        githubId: user.githubId,
35
        username: user.username,
36
        email: user.email,
37
        roles: user.roles,
38
        hasAcceptedTerms: user.hasAcceptedTerms,
39
      },
40
    };
41
  }
42
43
  private async getGithubToken(code: string): Promise<string> {
44 3
    const { data } = await firstValueFrom(
45
      this.httpService.post(
46
        'https://github.com/login/oauth/access_token',
47
        {
48
          client_id: this.configService.get('OAUTH_CLIENT_ID'),
49
          client_secret: this.configService.get('OAUTH_CLIENT_SECRET'),
50
          code,
51
        },
52
        {
53
          headers: { Accept: 'application/json' },
54
        },
55
      ),
56
    );
57 3
    return data.access_token;
58
  }
59
60
  private async getGithubUser(token: string): Promise<GithubUser> {
61 3
    const { data } = await firstValueFrom(
62
      this.httpService.get('https://api.github.com/user', {
63
        headers: {
64
          Authorization: `Bearer ${token}`,
65
          Accept: 'application/json',
66
        },
67
      }),
68
    );
69 3
    return data;
70
  }
71
72
  private async findOrCreateUser(githubUser: GithubUser): Promise<User> {
73 4
    let user = await this.userRepository.findOne({
74
      where: { githubId: githubUser.id },
75
    });
76
77 4
    if (!user) {
78 2
      user = await this.userRepository.save(
79
        new User({
80
          githubId: githubUser.id,
81
          username: githubUser.login,
82
          email: githubUser.email,
83
          avatarUrl: githubUser.avatar_url,
84
          roles: ['user'],
85
        }),
86
      );
87
    }
88
89 4
    return user;
90
  }
91
92
  private createToken(user: User): string {
93 2
    const payload: JwtPayload = {
94
      sub: user.githubId,
95
      username: user.username,
96
      email: user.email,
97
      roles: user.roles,
98
    };
99 2
    return this.jwtService.sign(payload);
100
  }
101
102
  async validateUserById(githubId: string): Promise<User | null> {
103 2
    return this.userRepository.findOne({ where: { githubId } });
104
  }
105
106
  async getStatus(user: User) {
107 1
    return {
108
      isAuthenticated: true,
109
      user: {
110
        githubId: user.githubId,
111
        username: user.username,
112
        email: user.email,
113
        roles: user.roles,
114
        hasAcceptedTerms: user.hasAcceptedTerms,
115
      },
116
    };
117
  }
118
}
119